package com.ofek.eventos.db;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.LocalBroadcastManager;

import com.ofek.applicationbase.broadcast.Delegate;
import com.ofek.eventos.EventosApplication;
import com.ofek.eventos.NewEventsActivity;
import com.ofek.eventos.R;
import com.ofek.eventos.db.EventosDatabaseService.DataListener;
import com.ofek.eventos.db.EventosDatabaseService.EventosDatabaseServiceBinder;
import com.ofek.eventos.db.datatypes.EventData;

public class EventosSyncService extends Service implements ServiceConnection, DataListener {


	public enum State {
		PROCESSING,
		IDLE
	}
	public interface StateListener {
		/**
		 * Called whenever the state of the SessionBuilder is changed and when first registered.
		 * <br>Running from some thread (most likely not the ui thread)
		 * @param s
		 */
		public void onStateUpdated(State s);
	}
	private final ArrayList<StateListener> listeners = new ArrayList<StateListener>();
	private State currentState = State.IDLE;
	private LocalBroadcastManager instance;

	private void setState(final State newState) {
		synchronized (currentState) {
			currentState = newState;
		}
		synchronized (listeners) {
			for (final StateListener sl : listeners) {
				sl.onStateUpdated(newState);
			}
		}
	}


	public State getState() { 
		synchronized (currentState) {
			return currentState;
		} 
	}
	public void registerStateListener(final StateListener l) {
		listeners.add(l);
	}
	public void unregisterStateListener(final StateListener l) {
		listeners.remove(l);
	}
	private void startNotification() {
		final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		final Intent intent = new Intent(this, NewEventsActivity.class);
		final PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
		final NotificationCompat.Builder mBuilder =
				new NotificationCompat.Builder(this)
		.setSmallIcon(android.R.drawable.ic_popup_sync)
		.setContentTitle(getString(R.string.app_name))
		.setContentText(getString(R.string.syncing_with_eventos_server_))
		.setContentIntent(pIntent);
		notificationManager.notify(0, mBuilder.build());
	}
	private void cancelNotification() {
		final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		notificationManager.cancel(0);
	}
	private EventosDatabaseService dbService;
	private Handler internetHandler;
	private SharedPreferences shPrefs;
	protected static final String LAST_SYNC_WITH_SERVER = "LAST_SYNC_WITH_SERVER";
	private static final int MINUTE = 60000;
	public static final String REQUEST_SYNC = "REQUEST_SYNC";

	@Override
	public IBinder onBind(final Intent arg0) {
		return new EventosSyncBinder();
	}
	public class EventosSyncBinder extends Binder {
		public EventosSyncService EventosSyncService() {
			return EventosSyncService.this;
		}
	}
	@Override
	public void onCreate() {
		super.onCreate();
		LocalBroadcastManager.getInstance(this).registerReceiver(new BroadcastReceiver() {

			@Override
			public void onReceive(final Context context, final Intent intent) {
				sync();
			}
		}, new IntentFilter(REQUEST_SYNC));
		final HandlerThread internetThread = new HandlerThread("EventosSyncServiceThread");
		internetThread.start();
		internetHandler = new Handler(internetThread.getLooper());
		bindService(new Intent(this, EventosDatabaseService.class), this, BIND_AUTO_CREATE);
		registerStateListener(new StateListener() {

			@Override
			public void onStateUpdated(final State s) {
				switch(s) {
				case IDLE:  cancelNotification(); break;
				case PROCESSING:  startNotification(); break;
				}
			}
		});
	}
	private final Runnable syncInFull = new Runnable() {

		@Override
		public void run() {

			sync();

			internetHandler.postDelayed(this, 10000);
		}
	};
	@Override
	public void onServiceConnected(final ComponentName arg0, final IBinder arg1) {
		dbService = ((EventosDatabaseServiceBinder) arg1).getEventosService();
		//sync();
		//fullSyncIn();
		dbService.registerDataListener(this);
		//internetHandler.postDelayed(syncInFull, 10000);
	}

	private final AtomicBoolean syncDue = new AtomicBoolean();
	private void sync() {
		if (EventosApplication.EVENTOS_USER==null || dbService==null || syncDue.get()) return;
		syncDue.set(true);
		internetHandler.post(new Runnable() {
			@Override
			public void run() {
				try {
					dbService.sync();
				}catch (final Exception e1) {
					e1.printStackTrace();
				} finally {
					setState(State.IDLE);
					syncDue.set(false);
				}
			}
		});
	}

	private final ArrayList<Delegate<EventData>> requestList = new ArrayList<Delegate<EventData>>();

	protected void sendNotificiation(final ArrayList<EventData> newEvents) {
		if (newEvents.size()<=0) return;

		final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		final Intent intent = new Intent(this, NewEventsActivity.class);
		intent.putExtra(NewEventsActivity.KEY_NEWEST, newEvents);
		final PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
		final NotificationCompat.Builder mBuilder =
				new NotificationCompat.Builder(this)
		.setSmallIcon(android.R.drawable.ic_dialog_email)
		.setContentTitle(getString(R.string.app_name))
		.setContentText(String.format(getString(R.string.new_requests_), newEvents.size()))
		.setContentIntent(pIntent);
		notificationManager.notify(1, mBuilder.build());
	}


	final SimpleDateFormat log_formatter = new SimpleDateFormat("dd-M-yyyy hh:mm:ss.SSS");



	@Override
	public void onServiceDisconnected(final ComponentName arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		unbindService(this);
		cancelNotification();
	}


	@Override
	public void onUpdate(final EventData older, final EventData newer) {
		sync();
	}


	@Override
	public void onAddition(final EventData added) {
		sync();	
	}


	@Override
	public void onRemoval(final EventData removed) {
		sync();
	}

	@Override
	public void onAddition(final List<EventData> all) {
		sync();
	}

}